#pragma once
#include <nlohmann/json.hpp>
#include "../commen/log.hpp"

using namespace ns_log;
using json = nlohmann::json;

// 基础模型接口
class IModel
{
public:
    virtual ~IModel() = default;
    virtual bool ToJson(json &j) const = 0;
    virtual bool FromJson(const json &j) = 0;
};

// 题目结构体
struct Question : public IModel
{
    int number;
    std::string title;
    std::string star;
    std::string desc;
    std::string header;
    std::string tail;
    int cpu_limit;
    int mem_limit;
    int commit_times;

    bool ToJson(json &j) const override
    {
        j = {
            {"number", number},
            {"title", title},
            {"star", star},
            {"description", desc},
            {"header", header},
            {"tail", tail},
            {"cpu_limit", cpu_limit},
            {"mem_limit", mem_limit},
            {"commit_times", commit_times}};
        return true;
    }

    bool FromJson(const json &j) override
    {
        try
        {
            number = j["number"].get<int>();
            title = j["title"].get<std::string>();
            star = j["star"].get<std::string>();
            desc = j["description"].get<std::string>();
            header = j["header"].get<std::string>();
            tail = j["tail"].get<std::string>();
            cpu_limit = j["cpu_limit"].get<int>();
            mem_limit = j["mem_limit"].get<int>();
            commit_times = j.value("commit_times", 0);
            return true;
        }
        catch (const std::exception &e)
        {
            LogMessage(Error, "Question FromJson failed: %s\n", e.what());
            return false;
        }
    }
};

// 提交记录结构体
struct SubmitRecord : public IModel
{
    int64_t id;
    int64_t uid;
    int number;
    std::string code;
    std::string status;
    std::string reason;
    std::string submit_time;

    bool ToJson(json &j) const override
    {
        j = {
            {"id", std::to_string(id)},
            {"uid", std::to_string(uid)},
            {"number", number},
            {"code", code},
            {"status", status},
            {"reason", reason},
            {"submit_time", submit_time}};
        return true;
    }

    bool FromJson(const json &j) override
    {
        try
        {
            id = std::stoll(j["id"].get<std::string>());
            uid = std::stoll(j["uid"].get<std::string>());
            number = j["number"].get<int>();
            code = j["code"].get<std::string>();
            status = j["status"].get<std::string>();
            reason = j["reason"].get<std::string>();
            submit_time = j["submit_time"].get<std::string>();
            return true;
        }
        catch (const std::exception &e)
        {
            LogMessage(Error, "SubmitRecord FromJson failed: %s\n", e.what());
            return false;
        }
    }
};

// 题单结构体
struct QuestionList : public IModel
{
    int64_t list_id;
    int64_t uid;
    std::string title;
    std::string description;
    bool is_public;
    std::string created_at;
    std::string updated_at;
    std::vector<Question> questions;

    bool ToJson(json &j) const override
    {
        json questions_array = json::array();
        for (const auto &q : questions)
        {
            json question_json;
            if (q.ToJson(question_json))
            {
                questions_array.push_back(question_json);
            }
        }

        j = {
            {"list_id", std::to_string(list_id)},
            {"uid", std::to_string(uid)},
            {"title", title},
            {"description", description},
            {"is_public", is_public},
            {"created_at", created_at},
            {"updated_at", updated_at},
            {"questions", questions_array}};
        return true;
    }

    bool FromJson(const json &j) override
    {
        try
        {
            list_id = std::stoll(j["list_id"].get<std::string>());
            uid = std::stoll(j["uid"].get<std::string>());
            title = j["title"].get<std::string>();
            description = j["description"].get<std::string>();
            is_public = j["is_public"].get<bool>();
            created_at = j["created_at"].get<std::string>();
            updated_at = j["updated_at"].get<std::string>();

            questions.clear();
            for (const auto &q_json : j["questions"])
            {
                Question q;
                if (q.FromJson(q_json))
                {
                    questions.push_back(q);
                }
            }
            return true;
        }
        catch (const std::exception &e)
        {
            LogMessage(Error, "QuestionList FromJson failed: %s\n", e.what());
            return false;
        }
    }
};